//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef __MISC_H_
#define __MISC_H_

#include <tfssys.h>
#include <math.h>
#include <stdio.h>

#ifndef _RELEASE
#define DPRINTF(x) kprintf x
#else
#define DPRINTF(x)
#endif


extern void Ktfs_Init_Lock(IMutex **ppLock);
extern void Ktfs_Lock(IMutex **ppLock);
extern void Ktfs_Unlock(IMutex **ppLock);
extern void Ktfs_Term_Lock(IMutex **ppLock);

#define ASSERT_DEBUG(a, b) \
    do{ \
        if (!(a)) { \
            assert(a);\
            DPRINTF(("%s\n", b)); \
        } \
    }while(0)

#define DEBUGOUT(s)

#define bzero(a,b) memset(a, 0, b)
#define bcopy(a,b,c) memcpy(b, a, c)

#define roundup(val, units) \
    ((((unsigned long)(val) + ((units) - 1)) / (units)) * (units))

typedef int (*intfun )(UInt32, void *, void *);
typedef int (__stdcall *intAssemblefun )(void *, void *, void *);

EXTERN_C void syslog(UInt32 errtype, wchar_t * Fmt, ...);

#define MAXSTAT 256    /*  ...in stat() response message */
/*
 * Values and macros relating to hardware pages
 */
#define NBPG (4096)    /* # bytes in a page */
#define NBBY (8)    /* # bits in a byte */
#define PGSHIFT (12)    /* LOG2(NBPG) */
#define ptob(x) ((UInt32)(x) << PGSHIFT)
#define btop(x) ((UInt32)(x) >> PGSHIFT)
#define btorp(x) (((UInt32)(x) + (NBPG-1)) >> PGSHIFT)

#define abs(a)  (a < 0)? -a:a
/*
 * Access modes
 */
#define ACC_READ       0x1
#define ACC_WRITE      0x2
#define ACC_APPEND     0x8
#define ACC_CREATE     0x10
#define ACC_FAILIFEXIST 0x20
#define ACC_CHMOD      0x40
#define ACC_EXEC       0x80
#define ACC_SYM        0x100
#define ACC_READONLY   0x400
#define ACC_DIR        0x800
#define DEFAULT_PERM   (ACC_READ|ACC_WRITE)

#define PERMLEN        7    /* Max levels of permission discrimination */
#define PERM_LEN(p)    (((p)->perm_len & ~0x80) % PERMLEN)
#define PERM_ACTIVE(p) ((p)->perm_len < PERMLEN)

typedef struct perm {
    UInt8 perm_len;            /* # slots valid */
    UInt8 perm_id[PERMLEN];    /* Permission values */
    UInt32 perm_uid;            /* UID for this ability */
} PERM;

typedef struct prot {
    UInt8 prot_len;            /* # slots valid */
    UInt8 prot_default;        /* Capabilities available to all */
    UInt8 prot_id[PERMLEN];    /* Permission values */
    UInt8                      /* Capabilities granted */
        prot_bits[PERMLEN];
} PROT;

#ifndef O_RDONLY
#define O_RDONLY    00
#endif

#ifndef O_WRONLY
#define O_WRONLY    01
#endif

#ifndef O_RDWR
#define O_RDWR      02
#endif

#ifndef _O_APPEND
#define _O_APPEND       0x0008  /* writes done at eof */
#endif

#ifndef O_CREAT
#define O_CREAT     0100
#endif

#ifndef O_EXCL
#define O_EXCL      0200
#endif

#ifndef O_TRUNC
#define O_TRUNC     01000
#endif

#ifndef O_APPEND
#define O_APPEND    02000
#endif

#ifndef SEEK_SET
#define SEEK_SET    0
#endif

#define    EPERM        (-1)     /* Not sufficient permissions */
#define    ESRCH        (-3)     /* No such file */
#define    EIO          (-5)     /* I/O error */
#define    EAGAIN       (-11)   /* Try again later */
#define    ENOMEM       (-12)    /* Out of memory */
#define    EBUSY        (-16)    /* File busy or Dir not empty */
#define    EEXIST       (-17)    /* File exists */
#define    ENOTDIR      (-20)    /* Not a directory */
#define    EISDIR       (-21)    /* Is a directory */
#define    EINVAL       (-22)    /* Invalid argument */
#define    ENOSPC       (-28)    /* No space left on device */
#define    EROFS        (-30)    /* Read only file system */
#define    EINVALHDL    (-31)    /* Invalid handle */
#define    ENOROOT      (-33)    /* No root had been mounted */
#define    ELAST        (-34)    /* Must be equal largest errno */
#define    ENOENTRY     (-35)    /* No directory entry */

#define FS_ERROR(ERROR) FILESYS_ERROR(ERROR)

//#define KTFS_DEBUGINFO

inline ECode ErrorToECODE(Int32 errno, const char* fn)
{
    switch (errno) {
        case 0:
            return NOERROR;

        case EINVAL:
            return E_INVALID_ARGUMENT;

        case ENOMEM:
            return E_OUT_OF_MEMORY;

        default:
            assert(errno <= EPERM && errno >= ENOENTRY);
            int nError = abs(errno);
            ECode ec = FS_ERROR(nError);
#ifdef KTFS_DEBUGINFO
            DPRINTF(("KTFS: Error in %s, errnor = %d, ec = 0x%08x\n", fn, nError, ec));
#endif
            return ec;
    }
}

#define PTR_ERR(err) ((unsigned long)(err))
#define IS_ERR(err) ((unsigned long)err > (unsigned long)-1000L)
#define ERR_PTR(type, err) ((type)(err))

#endif // __MISC_H_
